﻿using AiMoBridge.Interface;
using AiMoBridge.Paths;
using AiMoWindows.CodeScripts.IO;
using AiMoWindows.Localization;
using AiMoWindows.MainActions.SecondaryActions;
using AiMoWindows.Server;
using AiMoWindows.Windows.CommandLibrary.ViewModels;
using Microsoft.Win32;
using System.IO;

namespace AiMoWindows.MainActions.LibraryActions
{
    class LibraryActionsController(IDebugPrinter printer, IExecutor? executor, CommandLibraryViewModel owner)
    {
        readonly ScriptsLibraryManager scriptsLibraryManager = new ScriptsLibraryManager(executor, PathManager.CustomizedCommandsFolder, printer);
        readonly CommandLibraryViewModel owner = owner;
        readonly IDebugPrinter printer = printer;

        public void OnLoad()
        {
            owner.CommandItems.Clear();
            foreach (ScriptsLibraryItem item in scriptsLibraryManager.LoadExistedItems())
            {
                AddCommandItem(item);
            }
        }
        void AddCommandItem(ScriptsLibraryItem item)
        {
            CommandItemViewModel commandItem = new CommandItemViewModel(printer, item);
            commandItem.RemoveCurrent += owner.RemoveCommandItem;
            owner.CommanLibraryUI.AppendLanguageChangeModel(commandItem);
            owner.CommandItems.Add(commandItem);
        }
        public async void ExportRhpButton_Clicked()
        {
            owner.ClearPrint();
            if (owner.CommandItems.Count == 0)
            {
                printer.PrintDebug(Local.Get("No scripts items can be export"));
                return;
            }
            ScriptsLibraryItem[] canExportItems = owner.CommandItems.Where(x => !string.IsNullOrEmpty(x.ExportCommandEnglishName)).Select(x => x.OwnerItem).ToArray();
            if (canExportItems.Length == 0)
            {
                printer.PrintDebug(Local.Get("Please set item Command Name to export rhp"));
                return;
            }
            bool hasDuplicateName = false;
            for (int i = 0; i < canExportItems.Length - 1; i++)
            {
                for (int j = i + 1; j < canExportItems.Length; j++)
                {
                    if (canExportItems[i].CommandEnglishName ==
                        canExportItems[j].CommandEnglishName)
                    {
                        hasDuplicateName = true;
                        printer.PrintDebug(
                            string.Format(
                                Local.Get("Script {0} and script {1} cannot share same export command English Name {3}"),
                                canExportItems[i].Name, canExportItems[j].Name, canExportItems[i].CommandEnglishName));
                    }
                }
            }
            bool hasReferenceFiles = false;
            bool hasGrasshopperFiles = false;
            foreach (ScriptsLibraryItem item in canExportItems)
            {
                if (item.Script.ReferenceFiles.Length > 0)
                {
#warning 尝试支持外部dll导出~
                    printer.PrintDebug(string.Format(
                                Local.Get("Script {0} cannot be exported. Reference Assemblies are not supported yet."),
                                item.Name));
                    hasReferenceFiles = true;
                }
                if (item.Script.ScriptsMode == Mode.ScriptComplileMode.GrasshopperScript)
                {
                    printer.PrintDebug(string.Format(
                                Local.Get("Script {0} cannot be exported. Compile AiMo Grasshopper component into rhp is not supported."),
                                item.Name));
                    hasGrasshopperFiles = true;
                }
            }
            if (hasReferenceFiles || hasDuplicateName || hasGrasshopperFiles) return;
            Windows.InputString.InputStringDialog inputStringDialog = new Windows.InputString.InputStringDialog
            (
                titleEN: "Please input plugin author info.",
                titleCN: "请输入插件的作者名字。",
                labelEN: "Only items with English name can be exported. Link() method is not supported yet.",
                labelCN: "只有设定了英文名的代码才能导出，当前Link方法暂不支持。",
                defaultText: (ServerHelper.LogInAsCommunityUser ? ServerHelper.UserName : "AiMoUser")
            );
            inputStringDialog.ShowDialog();
            string authorText = inputStringDialog.UserInputString;
            if (inputStringDialog.DialogResult != true || string.IsNullOrEmpty(authorText))
            {
                owner.ShowMessage(Local.Get("Please input author name to export rhino plugin"));
                return;
            }
            printer.PrintDebug(string.Format(Local.Get("Find {0} script items can be export."), canExportItems.Length));
            string rhpFileToCopy = await scriptsLibraryManager.ExportRhp(canExportItems, authorText);
            printer.PrintDebug(scriptsLibraryManager.CompiledInfo);
            if (string.IsNullOrEmpty(rhpFileToCopy)) return;
            SaveFileDialog saveFileDialog = new SaveFileDialog()
            {
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
                RestoreDirectory = true,
                Title = Local.Get("Export commands to Rhp file"),
                DefaultExt = ".rhp",
                Filter = "*.rhp|rhp file",
                FileName = $"AiMoExport{DateTime.Now:MMdd}.rhp",
                OverwritePrompt = true,
            };
            if (saveFileDialog.ShowDialog() == true)
            {
                await Task.Run(() =>
                {
                    try
                    {
                        File.Copy(rhpFileToCopy, saveFileDialog.FileName, true);
                        ActionsUtils.SelectFileInWindows(saveFileDialog.FileName);
                    }
                    catch (Exception ex)
                    {
                        printer.PrintDebug($"Cannot save rhp file to {saveFileDialog.FileName}");
                        printer.PrintDebug(ex.Message);
                    }
                });

            }
        }
        public async void RunButton_Click()
        {
            if (owner.SelectedCommandItem != null)
            {
                owner.ClearPrint();
                await Task.Run(() =>
                {
                    if (scriptsLibraryManager.UpdateCompileItem(owner.SelectedCommandItem.OwnerItem) &&
                        scriptsLibraryManager.RunItem(owner.SelectedCommandItem.OwnerItem))
                    {
                        // Success Run a Command From Library
                    }
                });
            }
            else
            {
                printer.PrintDebug("No item selected");
            }
        }
        public void ImportScriptsButton_Clicked()
        {
            ExternalSettings.Load();
            OpenFileDialog ofd = new OpenFileDialog()
            {
                InitialDirectory = ExternalSettings.ScriptsFolderWithHistory,
                RestoreDirectory = true,
                CheckFileExists = true,
                Multiselect = true,
                Title = "Select AimoScript Files",
                Filter = $"AiMo Scripts File|*{CodeIO.Extension};*.AimoScipts",
            };
            if (ofd.ShowDialog() == true)
            {
                owner.ClearPrint();
                foreach (string file in ofd.FileNames)
                {
                    FileInfo fileInfo = new FileInfo(file);
                    if (scriptsLibraryManager.CheckCommandExisted(fileInfo, owner.CommandItems.Select(x => x.Name)))
                    {
                        ScriptsLibraryItem? item = scriptsLibraryManager.CreateCommandItem(fileInfo);
                        if (item != null) AddCommandItem(item);
                    }
                }
            }
        }
        public async void DownloadScriptButton_Click()
        {
            owner.ClearPrint();
            ScriptDownloader scriptDownloader = new ScriptDownloader(printer, Entrance.AiMoProgram.Instance);
            ScriptDownloadResult result = await scriptDownloader.DownloadScriptFromShareCode();
            if (result.Result)
            {
                FileInfo? fileInfo = scriptsLibraryManager.CreateDownloadScriptFile(result);
                if (fileInfo == null) return;
                if (scriptsLibraryManager.CheckCommandExisted(fileInfo, owner.CommandItems.Select(x => x.Name)))
                {
                    ScriptsLibraryItem? item = scriptsLibraryManager.CreateCommandItem(fileInfo);
                    if (item != null) AddCommandItem(item);
                }
            }
        }
    }
}
